package org.paybiz.core.payplatform.aliPay.service;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.paybiz.constant.PayConstant;
import org.paybiz.constant.ErrorConstant;
import org.paybiz.core.payplatform.aliPay.constant.AlipayConstant;
import org.paybiz.core.payplatform.aliPay.util.AlipayBase;
import org.paybiz.core.payplatform.aliPay.util.AlipayNotify;
import org.paybiz.core.payplatform.aliPay.util.SignatureHelper;
import org.paybiz.core.service.callback.AbstractPayCallback;
import org.paybiz.model.PayResultDO;
import org.paybiz.util.DynamicConfig;
import org.springframework.stereotype.Service;

/**
 * 支付回调
 * @author nassir.wen
 * @date 2013-1-8上午9:48:58
 * @company: MSD. 
 * @copyright: Copyright (c) 2013
 */
@Service("aliPayCallbackService")
public class AliPayCallbackServiceImpl extends AbstractPayCallback {

    private static final Log logger = LogFactory.getLog(AliPayCallbackServiceImpl.class);

    /**
     * 验证参数结果,模板方法由子类实现
     * @author nassir.wen
     * @date 2013-1-10下午2:51:25
     * @param request
     * @return
     */
    @Override
    protected PayResultDO verifyResult(HttpServletRequest request,HttpServletResponse response) {
        Map<String, String> params = requestParamsParse(request);
        //获取密钥
        String privateKey = DynamicConfig.getInstance().getValue(AlipayConstant.ali_keyValue);
        //本地签名
        String mysign = SignatureHelper.sign(params, privateKey);

        /**
         * 获取参数
         * notify_id: 通知校验ID,支付宝通知校验ID，商户可以用这个流水号询问支付宝该条通知的合法性。
         * trade_no: 第三方生成交易号
         * out_trade_no: 订单号
         * total_fee: 支付总金额
         * extra_common_param: 扩展参数，可以存放最后回调地址
         * sign: 签名
         * **/
        String responseTxt = AlipayNotify.Verify(params.get("notify_id"));
        String sign = params.get("sign");
        String order_id = params.get("out_trade_no");
        String trade_no = params.get("trade_no");
        double get_total_fee = Double.parseDouble(params.get("total_fee"));
        Integer money = (int) (get_total_fee * 100);
        String localResultUrl = "";
        try {
            localResultUrl = new String(params.get("extra_common_param").getBytes("ISO-8859-1"), "UTF-8");
            localResultUrl = URLDecoder.decode(localResultUrl, "UTF-8");
            logger.info("结果回调地址: " + localResultUrl);
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }
        //判断responsetTxt是否为ture，生成的签名结果mysign与获得的签名结果sign是否一致
        //responsetTxt的结果不是true，与服务器设置问题、合作身份者ID、notify_id一分钟失效有关
        logger.info("效验支付请求来源合法性:" + responseTxt);
        logger.info("本地签名:" + mysign + " 远程签名:" + sign);

        Integer result = PayConstant.RESULT_FAIL;
        String errMsg = "";
        try {
            //判断签名
            if (mysign.equals(sign)) {
                //判断支付状态
                if (params.get("trade_status").equals("TRADE_FINISHED")
                        || params.get("trade_status").equals("TRADE_SUCCESS")) {
                    logger.info("订单号:" + order_id + "支付宝支付成功！");
                    result = PayConstant.RESULT_SUCCESS;
                } else {
                    logger.info("订单号:" + order_id + "支付宝支付未成功！");
                }
            } else {
                //交易签名被篡改!
                errMsg = ErrorConstant.SIGN_FAIL_ID;
                logger.info("第三方 " + ErrorConstant.SIGN_FAIL_ID);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        PayResultDO payResultDO = new PayResultDO();
        payResultDO.setPayMoney(money);
        payResultDO.setOrderId(order_id);
        payResultDO.setPaySerialId(trade_no);
        payResultDO.setResult(result);
        payResultDO.setResultUrl(localResultUrl);
        payResultDO.setPayType(PayConstant.ALIPAY);
        payResultDO.setErrMsg(errMsg);
        return payResultDO;
    }

    private Map<String, String> requestParamsParse(HttpServletRequest request) {
        Map<String, String> params = new HashMap<String, String>();
        //获得POST 过来参数设置到新的params中
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            try {
                logger.info("原始值:" + name + ":" + valueStr);
                logger.info("UTF-8 解码后:" + new String(valueStr.getBytes("ISO-8859-1"), "UTF-8"));
                logger.info("GBK 解码后:" + new String(valueStr.getBytes("ISO-8859-1"), "GBK"));
                /*乱码解决，这段代码在出现乱码时使用,但是不一定能解决所有的问题，所以建议写过滤器实现编码控制。 如果mysign和sign不相等也可以使用这段代码转化*/
                valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            params.put(name, valueStr);
        }
        if (logger.isInfoEnabled()) {
            logger.info("解码后参数：" + AlipayBase.createLinkString(params));
        }
        return params;
    }

    /**
     * @author nassir.wen
     * @date 2013-1-10下午2:58:59
     * @see org.paybiz.core.service.callback.msd.payCenter.msdPay.service.AbstractPayCallback#send(int)
     * @param result
     * @return
     */
    @Override
    protected String send(int result) {
        return result == PayConstant.RESULT_SUCCESS ? "success" : "fail";
    }

}
